/*
 * HeuristicTwo.cpp
 *
 *  Created on: Dec 30, 2009
 *      Author: ssperetz
 */

#include "HeuristicTwo.h"


HeuristicTwo::HeuristicTwo(const SmartSenetBoard & curBoard) {
	
	int boradSize = curBoard.m_size_squares;
    double pieceFactor = boradSize / 2;
    double sequenceFactor = boradSize;
    double safeFactor = boradSize / 3;

	int maxThreeSequences = curBoard.m_num_pieces / 3;

	int maxSafe = curBoard.m_num_extra_safe + 3;

	maxHeuristic = (curBoard.m_num_pieces * curBoard.m_size_squares)
			+ (curBoard.m_num_pieces * pieceFactor)
			+ (maxThreeSequences * sequenceFactor) 
			+ (maxSafe * safeFactor);
	minHeuristic = -maxHeuristic;
}

HeuristicTwo::~HeuristicTwo() {
	// TODO Auto-generated destructor stub
}

double HeuristicTwo::getBoradHeuristic(const SmartSenetBoard & curBoard,
		const Definitions::PlayerColor myColor) {
	double sumOFMyPiecesDistances = 0.0;
	double sumOFOpponentPiecesDistances = 0.0;
	int boradSize = curBoard.m_size_squares;
	int initialNumOfPieces = curBoard.m_num_pieces;
	double pieceFactor = boradSize / 2;
	int curNumOfMyPieces;
	int curNumOfOpponentPieces;
	bool sawOpponent = false;
	bool sawMe = false;

	int myTwoSequence = 0;
	int myThreeSequence = 0;
	int opponentTwoSequence = 0;
	int opponentThreeSequence = 0;

	int sequenceMyChecker = 0;
	int sequenceOpponentChecker = 0;

	double sequenceFactor = boradSize;

	int curOutOfTheBoardMyPieces = curBoard.m_num_pieces;
	int curOutOfTheBoardOpponentPieces = curOutOfTheBoardMyPieces;

	int numOfMySafe = 0;
	int numOfOpponentSafe = 0;

	double safeFactor = boradSize / 3;

	for (int i = 0; i < boradSize; i++) {
		if (curBoard.m_boardState[i].player_color == myColor) {
			curOutOfTheBoardMyPieces--;
			sumOFMyPiecesDistances += i;
			
			if (curBoard.m_boardState[i].square_type == SmartSenetBoard::SAFE)
				numOfMySafe++;

			sawMe = true;

			if (sequenceOpponentChecker == 2)
				opponentTwoSequence++;
			sequenceOpponentChecker = 0;
			if (sawOpponent) {
				sequenceMyChecker++;
				// sequences from 3 are consider once
				if (sequenceMyChecker == 3)
					myThreeSequence++;

			}

		}
		// If square player color is different than None then it must be opponent color
		else if (curBoard.m_boardState[i].player_color != Definitions::NONE) {
			curOutOfTheBoardOpponentPieces--;
			sumOFOpponentPiecesDistances += i;

			if (curBoard.m_boardState[i].square_type == SmartSenetBoard::SAFE)
				numOfOpponentSafe++;

			sawOpponent = true;
			if (sequenceMyChecker == 2)
				myTwoSequence++;
			sequenceMyChecker = 0;
			if (sawMe) {
				sequenceOpponentChecker++;
				// sequences from 3 are consider once
				if (sequenceOpponentChecker == 3)
					opponentThreeSequence++;

			}
		} else { // an empty square

			if (sequenceOpponentChecker == 2)
				opponentTwoSequence++;
			if (sequenceMyChecker == 2)
				myTwoSequence++;
			sequenceMyChecker = 0;
			sequenceOpponentChecker = 0;
		}
	}
	sumOFMyPiecesDistances += (boradSize * curOutOfTheBoardMyPieces);
	sumOFOpponentPiecesDistances
			+= (boradSize * curOutOfTheBoardOpponentPieces);

	curNumOfMyPieces = initialNumOfPieces - curOutOfTheBoardMyPieces;
	curNumOfOpponentPieces = initialNumOfPieces
			- curOutOfTheBoardOpponentPieces;

	return ((sumOFMyPiecesDistances - sumOFOpponentPiecesDistances)
			- (curNumOfMyPieces * pieceFactor) + (curNumOfOpponentPieces
			* pieceFactor) + (myThreeSequence * sequenceFactor)
			+ (myTwoSequence * sequenceFactor / 2) - (opponentThreeSequence
			* sequenceFactor) - (opponentTwoSequence * sequenceFactor / 2))
			+ (numOfMySafe * safeFactor) - (numOfOpponentSafe * safeFactor);
}
